package main

import (
	"fmt"
	"net"
	"sync/atomic"
	"time"
)

func main() {
	serverAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:8080")
	if err != nil {
		panic(err)
	}

	conn, err := net.DialUDP("udp", nil, serverAddr)
	if err != nil {
		panic(err)
	}
	defer conn.Close()

	// 使用原子操作的统计变量，避免锁竞争
	var packetCount int64
	var byteCount int64

	// 启动一个goroutine来处理定时打印
	done := make(chan bool)
	go func() {
		ticker := time.NewTicker(1 * time.Second)
		defer ticker.Stop()

		var lastPacketCount, lastByteCount int64

		for {
			select {
			case <-ticker.C:
				// 获取当前统计值
				currentPacketCount := atomic.LoadInt64(&packetCount)
				currentByteCount := atomic.LoadInt64(&byteCount)

				// 计算这一秒的速率
				packetRate := currentPacketCount - lastPacketCount
				byteRate := currentByteCount - lastByteCount

				fmt.Printf("Rate: %d packets/sec | %d bytes/sec | Total packets: %d | Total bytes: %d\n",
					packetRate, byteRate, currentPacketCount, currentByteCount)

				// 更新上次统计的值
				lastPacketCount = currentPacketCount
				lastByteCount = currentByteCount
			case <-done:
				// 最后一次统计
				currentPacketCount := atomic.LoadInt64(&packetCount)
				currentByteCount := atomic.LoadInt64(&byteCount)
				fmt.Printf("Final rate: %d packets/sec | %d bytes/sec | Total packets: %d | Total bytes: %d\n",
					currentPacketCount-lastPacketCount, currentByteCount-lastByteCount,
					currentPacketCount, currentByteCount)
				return
			}
		}
	}()

	// 发送数据包
	for i := 0; i < 1000000; i++ {
		message := fmt.Sprintf("Packet %d", i)
		_, err = conn.Write([]byte(message))
		if err != nil {
			fmt.Println("Send error:", err)
			continue
		}

		// 更新统计信息
		atomic.AddInt64(&packetCount, 1)
		atomic.AddInt64(&byteCount, int64(len(message)))

		// 每隔一定数量打印一次发送信息，避免输出过多
		if i%50000 == 0 {
			fmt.Printf("Sent: %s\n", message)
		}
	}

	// 通知定时打印goroutine结束并等待一小段时间以确保最后的信息被打印
	close(done)
	time.Sleep(100 * time.Millisecond)

	// 打印最终统计信息
	finalPacketCount := atomic.LoadInt64(&packetCount)
	finalByteCount := atomic.LoadInt64(&byteCount)
	fmt.Printf("\nFinal statistics:\n")
	fmt.Printf("Total packets sent: %d\n", finalPacketCount)
	fmt.Printf("Total bytes sent: %d\n", finalByteCount)
}
